/*
*    Reversi Contender homepage:  http://code.google.com/p/reversi-contender
*
*    copyright 2011 steven sims <steven.joseph.sims at gmail.com>
*
*    This file is part of Reversi Contender.
*
*    Reversi Contender is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    Reversi Contender is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with Reversi Contender.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.threadswarm.reversi.gui;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.LineBorder;
import org.jdesktop.core.animation.timing.Animator;
import org.threadswarm.reversi.GameSession;
import org.threadswarm.reversi.Main;
import org.threadswarm.reversi.Status;
import org.threadswarm.reversi.gui.animation.AlphaSettingTimingTarget;
import org.threadswarm.reversi.gui.animation.AnimationType;
import org.threadswarm.reversi.gui.animation.AnimatorRepository;

/**
 *
 * @author steve
 */
public class PreferencesActionListener implements ActionListener {
    
    private final static GameSession GAME_SESSION = GameSession.getInstance();
    private final static AnimatorRepository ANIMATOR_REPO = AnimatorRepository.getInstance();

    private final JFrame frame;
    private JDialog dialog = null;

    public PreferencesActionListener(JFrame frame) {
        this.frame = frame;
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        if(dialog == null){
            dialog = new JDialog(frame, "Edit Preferences", true);
            dialog.setResizable(false);
            JPanel contentPanel = (JPanel) dialog.getContentPane();
            contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
            
            JPanel playerAndInterfacePanel = new JPanel();
            playerAndInterfacePanel.setLayout(new FlowLayout());

            JPanel playerPanel = new JPanel();
            playerPanel.setBorder(BorderFactory.createTitledBorder(new LineBorder(Color.BLACK), "Color"));
            playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.Y_AXIS));
            ButtonGroup radioGroup = new ButtonGroup();
            JRadioButton blackButton = new JRadioButton("BLACK");
            JRadioButton whiteButton = new JRadioButton("WHITE");
            radioGroup.add(blackButton);
            radioGroup.add(whiteButton);
            playerPanel.add(blackButton);
            playerPanel.add(whiteButton);
            if(GAME_SESSION.getPlayerStatus() == Status.BLACK){
                blackButton.setSelected(true);
            }else{
                whiteButton.setSelected(true);
            }
            playerAndInterfacePanel.add(playerPanel);

            JPanel interfacePanel = new JPanel();
            interfacePanel.setBorder(BorderFactory.createTitledBorder(new LineBorder(Color.BLACK), "Interface Options"));
            interfacePanel.setLayout(new BoxLayout(interfacePanel, BoxLayout.Y_AXIS));
            JCheckBox markCheckBox = new JCheckBox("Show valid moves/insertions");
            if(GAME_SESSION.isMarkAvailable())
                markCheckBox.setSelected(true);
            JCheckBox animateInsertionsCheckBox = new JCheckBox("Animate available insertions");
            if(GAME_SESSION.isAvailInsertionAnimationEnabled())
                animateInsertionsCheckBox.setSelected(true);
            interfacePanel.add(markCheckBox);
            interfacePanel.add(animateInsertionsCheckBox);
            playerAndInterfacePanel.add(interfacePanel);
            
            contentPanel.add(playerAndInterfacePanel);
            
            JPanel botPanel = new JPanel();
            botPanel.setBorder(BorderFactory.createTitledBorder(new LineBorder(Color.BLACK), "AI Configuration"));
            botPanel.setLayout(new FlowLayout());
            JLabel depthLabel = new JLabel("Look-ahead search depth");
            JSpinner depthSpinner = new JSpinner(new SpinnerNumberModel(GAME_SESSION.getDepth(), 1, 20, 1));
            botPanel.add(depthLabel);
            botPanel.add(depthSpinner);
            if(!GAME_SESSION.isAdvancedMode()){
                botPanel.setVisible(false);
            }

            contentPanel.add(botPanel);

            JPanel controlPanel = new JPanel();
            controlPanel.setLayout(new FlowLayout());
            JButton saveButton = new JButton("Save");
            SaveButtonActionListener saveButtonActionListener = new SaveButtonActionListener();
            saveButtonActionListener.setAnimateAvailInsertionsCheckBox(animateInsertionsCheckBox);
            saveButtonActionListener.setBlackButton(blackButton);
            saveButtonActionListener.setMarkCheckBox(markCheckBox);
            saveButtonActionListener.setDepthSpinner(depthSpinner);
            saveButton.addActionListener(saveButtonActionListener);
            controlPanel.add(saveButton);
            JButton cancelButton = new JButton("Close");
            cancelButton.addActionListener(new CancelButtonActionListener());
            controlPanel.add(cancelButton);
            contentPanel.add(controlPanel);

            dialog.pack();
        }
        dialog.setLocationRelativeTo(frame);
        dialog.setVisible(true);
    }

    private class SaveButtonActionListener implements ActionListener {

        private JRadioButton blackButton;
        private JCheckBox markCheckBox;
        private JSpinner depthSpinner;
        private JCheckBox animateAvailInsertionsCheckBox;
        
        

        public void setAnimateAvailInsertionsCheckBox(JCheckBox animateAvailInsertionsCheckBox) {
            this.animateAvailInsertionsCheckBox = animateAvailInsertionsCheckBox;
        }

        public void setBlackButton(JRadioButton blackButton) {
            this.blackButton = blackButton;
        }

        public void setDepthSpinner(JSpinner depthSpinner) {
            this.depthSpinner = depthSpinner;
        }

        public void setMarkCheckBox(JCheckBox markCheckBox) {
            this.markCheckBox = markCheckBox;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            boolean reloadGame = false;

            GAME_SESSION.setMarkAvailable(markCheckBox.isSelected());
            
            boolean animateInsertions = animateAvailInsertionsCheckBox.isSelected();
            GAME_SESSION.setAvailInsertionAnimationEnabled(animateInsertions);
            Animator insertionAnimator = ANIMATOR_REPO.getAnimator(AnimationType.AVAIL_INSERTION);
            if(!animateInsertions && insertionAnimator.isRunning()){
                insertionAnimator.stop();          
            }else if(animateInsertions && !insertionAnimator.isRunning()){
                List<CellComponent> availableInsertions = GAME_SESSION.getAvailableInsertionsList();
                insertionAnimator.addTarget(new AlphaSettingTimingTarget(availableInsertions));
                insertionAnimator.start();
            }
            
            resetAvailableInsertions(GAME_SESSION.getAvailableInsertionsList());

            Status status = (blackButton.isSelected())? Status.BLACK : Status.WHITE;
            if(status != GAME_SESSION.getPlayerStatus()){
                reloadGame = true;
            }

            int depth = (Integer) depthSpinner.getValue();
            if(depth != GAME_SESSION.getDepth())
                GAME_SESSION.setDepth(depth);

            if(reloadGame){
                int confirmValue = JOptionPane.showConfirmDialog(dialog, "Changing player color requires the game to restart.", "Restart Required", JOptionPane.OK_CANCEL_OPTION);
                if(confirmValue == 0){
                    dialog.setVisible(false);
                    GAME_SESSION.setPlayerStatus(status);
                    Main.getGameContentPanel(frame);
                }
            }

            dialog.setVisible(false);
        }
        
        private void resetAvailableInsertions(Collection<CellComponent> cellComponents) {
            for(CellComponent cellComponent : cellComponents){
                cellComponent.setAlpha(0.2f);
                cellComponent.refresh();
            }
        }

    }

    private class CancelButtonActionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent ae) {
            dialog.setVisible(false);
        }

    }

}
